package cn.touna.jss.modules.third.geo;

import cn.touna.risk.api.enums.SystemErrorCodeEnum;
import cn.touna.jss.common.entity.NameMobileEntity;
import cn.touna.jss.common.entity.ThreeElementEntity;
import cn.touna.jss.common.factory.ResponseFactory;
import cn.touna.jss.common.properties.disconf.GeoProperties;
import cn.touna.jss.common.util.HttpUtil;
import cn.touna.jss.common.util.Secret;
import cn.touna.jss.common.util.ValidUtil;
import cn.touna.jss.modules.adapter.ApiMapping;
import cn.touna.jss.modules.third.geo.component.GeoDataResult;
import cn.touna.risk.api.domain.Response;
import cn.touna.risk.cache.redis.RedisCache;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.touna.loan.log.service.TracerContextUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * <P>集奥聚合</P>
 * User: wuwc
 * Date: 2017/7/31
 * Time: 11:05
 */
@Service
public class GeoService {

    private static final Logger logger = LoggerFactory.getLogger(GeoService.class);

    @Autowired
    private GeoProperties config;

    @Autowired
    private GeoDataResult geoDataResult;

    /**
     * 集奥聚合:手机号码身份证号姓名验证接口
     *
     * @param request
     * @return
     * @throws Exception
     */
//    @ApiMapping("geo.threeBaseData")
//    public Response threeBaseData(ThreeElementEntity request) throws Exception {
//        Response response = ValidUtil.valid(request);
//        if(response != null){
//            return response;
//        }
//        try{
//            String res = geoDataResult.getThreeBaseData(request.getMobile(),request.getIdCard(),request.getName());
//            return ResponseFactory.success(JSONObject.parseObject(res));
//        }catch (Exception e){
//            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR,e.getMessage());
//        }
//    }

    /**
     * 集奥聚合:手机号码姓名验证接口
     *
     * @param request
     * @return
     * @throws Exception
     */
    @ApiMapping(value = "geo.mobileNameCheck",desc = "集奥.手机号码姓名验证接口")
    public Response mobileNameCheck(NameMobileEntity request) {
        Response response = ValidUtil.valid(request);
        if(response != null){
            return response;
        }
        try{
            String res = geoDataResult.getMobileNameCheckData(request.getMobile(),request.getName());
            return ResponseFactory.success(JSONObject.parseObject(res));
        }catch (Exception e){
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR,e.getMessage());
        }
    }

    /**
     * 集奥聚合:A3-手机号码在网时长查询接口
     *
     * @param request
     * @return
     * @throws Exception
     */
    @ApiMapping(value = "geo.mobileNumberOnlineTime",desc = "集奥.A3-手机号码在网时长查询接口")
    public Response mobileNumberOnlineTime(ThreeElementEntity request) throws Exception {
        Response response = ValidUtil.valid(request);
        if(response != null){
            return response;
        }

        try{
            String res = geoDataResult.getMobileNumberOnlineTime(request.getMobile(),request.getIdCard(),request.getName());
            return ResponseFactory.success(JSON.parseObject(res));
        }catch (Exception e){
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR,e.getMessage());
        }
    }


    @Autowired
    private RedisCache redisCache;

    /**
     * 登录，并返回tokenId
     * @param force 为true，表示强制从新获取，为false时，表示优先从缓存中获取
     * @return
     */
    private String login(boolean force) throws Exception {
        String tokenIdKey = "jss:geo:tokenId";
        String tokenId = null;
        if(!force){
            if(redisCache.exist(tokenIdKey)){
                tokenId = redisCache.get(tokenIdKey);
            }
            if(!StringUtils.isEmpty(tokenId)){
                return tokenId;
            }
        }
        //是否进行数字签名1是、0或空否，(该参数可加密)
        int dsign = 0;
        //是否密文传输1是、0或空否，该参数不能加密
        int encrypted = 1;

        // 加密用户名密码
        String eUsername = encrypt(config.getUsername());
        String ePassword = encrypt(config.getPassword());
        String eDsign = encrypt(dsign);
        Map<String,String> params = new HashMap<>();

        params.put("username",eUsername);
        params.put("password",ePassword);
        params.put("dsign",eDsign);
        params.put("uno",config.getUno());
        params.put("encrypted",String.valueOf(encrypted));

        String res = HttpUtil.get(config.getLoginUrl(),params);
        res = decrypt(res);

        JSONObject resObj = JSONObject.parseObject(res);
        String code = resObj.getString("code");
        if("200".equals(code)) {
            JSONObject data = resObj.getJSONObject("data");
            tokenId =  data.getString("tokenId");
            redisCache.set(tokenIdKey,tokenId,1, TimeUnit.DAYS);
            return tokenId;
        }else {
            String msg = resObj.getString("msg");
            throw new Exception(code + ":" + msg);
        }
    }

    private String encrypt(Object value){
        return Secret.encrypt(config.getEncryptionType(), String.valueOf(value) , config.getEncryptionKey());
    }

    private String decrypt(String value){
        return Secret.decrypt(config.getEncryptionType(),value,config.getEncryptionKey());
    }

    /**
     * 集奥，验证身份证，姓名，手机号
     * @param request
     * @return
     */
    @ApiMapping(value = "geo.threeBaseData",desc = "集奥.三要素验证")
    public Response threeBaseData(ThreeElementEntity request){
        Response response = ValidUtil.valid(request);
        if(response != null)
            return response;

        Map<String,String> params = new HashMap<>();
        params.put("innerIfType",encrypt("B7"));
        params.put("cid",encrypt(request.getMobile()));
        params.put("idNumber",encrypt(request.getIdCard()));
        params.put("realName",encrypt(request.getName()));
        String authCode = config.getUno() + ":" + TracerContextUtil.getTraceId();
        params.put("authCode",encrypt(authCode));
        try {
            return getData(config.getQueryUnifyUrl(),params,false);
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_CALL_EXTSYSTEM_ERROR,e.getMessage());
        }
    }

    /**
     * 获取数据
     * @param url
     * @param params
     * @param force force=false 优先从缓存中获取tokenId
     * @return
     * @throws Exception
     */
    private Response getData(String url,Map<String,String>params,boolean force) throws Exception {
        String tokenId = null;
        try {
            tokenId = login(force);
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_FAIL,e.getMessage());
        }

        params.put("tokenId",tokenId);
        String res = HttpUtil.get(url,params);
        res = decrypt(res);
        JSONObject resObj = JSONObject.parseObject(res);
        String code = resObj.getString("code");
        if("200".equals(code)) {
            return ResponseFactory.success(resObj);
        }else if("-100".equals(code) || "-200".equals(code) || "-300".equals(code)){
//            -100	token为空（需要重新获tokenID）
//            -200	用户被新登录挤掉（需要重新获tokenID）
//            -300	用户未登录（需要重新获tokenID）
            //需要重新登录，再次调用
            return getData(url,params,true);
        }else{
            String msg = resObj.getString("msg");
            return ResponseFactory.fail(SystemErrorCodeEnum.JSS_EXTSYSTEM_RESP_FAIL,code + ":" + msg,resObj);
        }
    }






}
